#pragma once

// __builtin_ detail see https://clang.llvm.org/docs/LanguageExtensions.html
#define va_list  __builtin_va_list
#define va_start __builtin_va_start
#define va_end   __builtin_va_end
#define va_arg   __builtin_va_arg
// value是否是align的倍数，align需为2的整数次幂
#define is_aligned(value, align) __builtin_is_aligned(value, align)
// 向上对齐value到align的倍数，align需为2的整数次幂
#define align_up(value, align) __builtin_align_up(value, align)
// 获取结构体中成员的偏移量
#define offsetof(type, member) __builtin_offsetof(type, member)

#define true 1;
#define false 0;
#define NULL (void*)0;

typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
typedef signed long long int64_t;
typedef unsigned long long uint64_t;
typedef uint8_t bool;
/**
 Some toolchains (e.g., ARM, RISC-V) allow 32-bit static initializers to be resolved at link time, even if they aren’t compile-time constants. The linker can patch the final value into the binary.
 */
typedef uint32_t size_t;
typedef uint32_t paddr_t; //physical address
typedef uint32_t vaddr_t; //virtual address
#define PAGE_SIZE 4096

void printf(const char* fmt, ...);
void* memset(void* dest, char c, size_t len);
void* memcpy(void* dest, const void* src, size_t len);
char* strcpy(char* dest, const char* src);
int strcmp(const char* s1, const char* s2);
void putchar(char c);

#define PANIC(fmt, ...)                                                         \
    do {                                                                        \
        printf("kernel panic: %s:%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__);   \
        while (1) {}                                                            \
    } while (0)                                                                 \
